// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: listener code decoupling
// ------------------------------------------------------------------

#include <security/logging/LogTopic.h>

#include <ertps/publisher/Publisher.h>
#include <elog/log/Log.h>

namespace evbs {
namespace ertps {
namespace rtps {
namespace security {

LogTopic::LogTopic()
    : stop_(false), thread_([this]() {
          for (;;) {
              // Put the thread asleep until there is
              // something to process
              auto p = queue_.wait_pop();

              if (!p) {
                  if (stop_) {
                      return;
                  }
                  continue;
              }

              publish(*p);
          }
      }) {
    //
}

LogTopic::~LogTopic() {
    stop();
    try {
        queue_.push(BuiltinLoggingTypePtr(nullptr));
    } catch (const std::exception& e) {}

    if (thread_.joinable()) {
        thread_.join();
    }

    if (file_stream_.is_open()) {
        file_stream_.close();
    }
}

void LogTopic::log_impl(const BuiltinLoggingType& message, SecurityException& /*exception*/) const {
    queue_.push(BuiltinLoggingTypePtr(new BuiltinLoggingType(message)));
}

bool LogTopic::enable_logging_impl(SecurityException& exception) {
    LogOptions options;
    if (!get_log_options(options, exception)) {
        return false;
    }

    if (!options.log_file.empty()) {
        file_stream_.open(options.log_file, std::ios::out | std::ios::app);

        if ((file_stream_.rdstate() & std::ofstream::failbit) != 0) {
            exception = SecurityException("Error opening file: " + options.log_file);
            return false;
        }
    }

    return true;
}

void LogTopic::publish(BuiltinLoggingType& builtin_msg) {
    SecurityException exception;
    if ((!file_stream_.is_open()) || (!compose_header(file_stream_, builtin_msg, exception))) {
        return;
    }

    file_stream_ << " : " << builtin_msg.message << "\n";
    (void)file_stream_.flush();
}

}  // namespace security
}  // namespace rtps
}  // namespace ertps
}  // namespace evbs
